﻿using System;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace ErickOrlando.Utilidades.Seguridad
{
    /// <summary>
    /// Clase de Seguridad
    /// </summary>
    /// <remarks>Erick Orlando © 2008-2011</remarks>
    [DebuggerNonUserCode()]
    internal class Criptografia : IDisposable
    {

        #region   Métodos de Negocio

        private SymmetricAlgorithm ENC;
        private MemoryStream objOutputStream;
        private string password = string.Empty;

        public Criptografia()
        {
            Constructor(ConfigurationManager.AppSettings["Acronimo"]);
        }

        public Criptografia(string pass)
        {
            Constructor(pass);
        }

        private void Constructor(string pass)
        {
            ENC = new TripleDESCryptoServiceProvider();
            //Inicializamos la clave de seguridad y el vector de inicializacion
            var sltBytes = new byte[] { 101, 102, 103, 104, 105, 106, 107, 108 };
            password = pass;
            Rfc2898DeriveBytes psswdBytes = new Rfc2898DeriveBytes(password, sltBytes);

            //Creamos una nueva instancia de la clase TripleDESCryptoServiceProvider
            ENC.Key = psswdBytes.GetBytes((int)ENC.LegalKeySizes[0].MinSize / 8);
            ENC.IV = psswdBytes.GetBytes((int)ENC.LegalBlockSizes[0].MinSize / 8);
        }

        /// <summary>
        /// Encripta una Cadena
        /// </summary>
        public string Encrypt(string cadena)
        {
            try
            {
                var bytInput = Encoding.UTF8.GetBytes(cadena);

                using (var salida = new MemoryStream())
                {

                    var CS = new CryptoStream(salida, ENC.CreateEncryptor(), CryptoStreamMode.Write);
                    CS.Write(bytInput, 0, bytInput.Length);
                    CS.FlushFinalBlock();

                    return Convert.ToBase64String(salida.ToArray());
                }

            }
            catch (Exception ExceptionErr)
            {
                throw new Exception(ExceptionErr.Message, ExceptionErr.InnerException);
            }
        }

        /// <summary>
        /// Desencripta una cadena
        /// </summary>
        public string Decrypt(string cadena)
        {
            try
            {
                var bytInput = Convert.FromBase64String(cadena);

                using (var salida = new MemoryStream())
                {
                    var CS = new CryptoStream(salida, ENC.CreateDecryptor(), CryptoStreamMode.Write);
                    CS.Write(bytInput, 0, bytInput.Length);
                    CS.FlushFinalBlock();

                    return Encoding.UTF8.GetString(salida.ToArray());
                }

            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex.InnerException);
            }
        }

        #endregion

        #region IDisposable
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (ENC != null)
                {
                    ENC.Dispose();
                    ENC = null;
                }
                if (objOutputStream != null)
                {
                    objOutputStream.Dispose();
                    objOutputStream = null;
                }
            }
        }
        ~Criptografia()
        {
            Dispose(false);
        }
        #endregion


    }
}
